﻿/* Copyright 2010 Igor Francé
 * 
 * This file is part of ECMADoc (http://ecmadoc.codeplex.com).
 * 
 * ECMADoc is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * ECMADoc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with ECMADoc. 
 * If not, see http://www.gnu.org/licenses/.
 */
namespace EcmaDoc.Core.Items
{
	using System;
	using System.Collections.Generic;

	using EcmaDoc.Core.Configuration;

	/// <summary>
	/// Represents an object code item.
	/// </summary>
	public class ObjectItem : CodeItem
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="ObjectItem"/> class, using the specified
		/// <paramref name="parentItem"/> and <paramref name="name"/>.
		/// </summary>
		/// <param name="parentItem">The parent item that this code item belongs to.</param>
		/// <param name="name">The name of this object item.</param>
		public ObjectItem(CodeItem parentItem, string name)
			: this(parentItem, name, (Comment) null)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ObjectItem"/> class, using the specified
		/// <paramref name="parentItem"/>, <paramref name="name"/> and <paramref name="commentString"/>.
		/// </summary>
		/// <param name="parentItem">The parent item that this code item belongs to.</param>
		/// <param name="name">The name of this object item.</param>
		/// <param name="commentString">The comment string for this object item.</param>
		public ObjectItem(CodeItem parentItem, string name, string commentString)
			: this(parentItem, name, (Comment) null)
		{
			this.Comment = Comment.Create(commentString, this);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ObjectItem"/> class, using the specified
		/// <paramref name="parentItem"/>, <paramref name="name"/> and <paramref name="comment"/>.
		/// </summary>
		/// <param name="parentItem">The parent item that this code item belongs to.</param>
		/// <param name="name">The name of this object item.</param>
		/// <param name="comment">The parsed comment for this object item.</param>
		public ObjectItem(CodeItem parentItem, string name, Comment comment)
			: base(parentItem, name, comment)
		{
			this.Type = ParserConfig.DefaultBaseType;
		}

		/// <summary>
		/// Gets the documentation URL of this code item.
		/// </summary>
		/// <value></value>
		public override string Url
		{
			get
			{
				NamespaceItem ns = this.OwnerNamespace;
				string extension = this.OwnerProject.Info.FileExtension;
				string suffix = CodeItem.GetFileNameSuffix(this.Visibility);
				bool singlePage = this.OwnerProject.Info.SinglePageMemberDetail;

				string namespaceName = ns != null ? ns.FullName : string.Empty;

				CodeItem c = this;
				List<string> segments = new List<string>();
				while (c != null && !(c is NamespaceItem))
				{
					segments.Add(c.Name);
					c = c.Parent;
				}

				segments.Reverse();
				string itemName = segments[0];
				segments.RemoveAt(0);

				string url = namespaceName;
				if (singlePage)
				{
					url += "." + itemName + extension;
					if (segments.Count != 0)
					{
						url += "#" + segments.Join(".");
					}
				}
				else
				{
					url += "." + itemName;
					if (segments.Count != 0)
						url += "." + segments.Join(".");

					url += suffix + extension;
				}

				return CodeItem.GetValidFileName(url);
			}
		}

		/// <summary>
		/// Gets the name of the xml node that represents this code item.
		/// </summary>
		/// <returns>
		/// The <see cref="ItemType"/> string converted to lower case.
		/// </returns>
		internal override string GetNodeName()
		{
			if (this.ItemType != ItemType.Object)
				return base.GetNodeName();

			if (Parent.ItemType == ItemType.Enumeration)
				return "value";

			if (Parent.ItemType == ItemType.Namespace)
			{
				if (MemberCount == 0)
					return "variable";

				return "object";
			}

			return "property";
		}

		/// <summary>
		/// Gets a string that specified a short example of this code item's usage.
		/// </summary>
		/// <param name="extended">If <c>true</c>, the resulting string will be HTML with links to other types.</param>
		/// <returns>
		/// A string that specified a short example of this code item's usage
		/// </returns>
		protected internal override string GetSynopsis(bool extended)
		{
			if (this.Parent.ItemType == ItemType.Enumeration)
				return null;
			if (this.ItemType == ItemType.Event)
				return null;

			var isVariable = 
				this.Parent.ItemType == ItemType.Namespace || this.Visibility == Visibility.Private;

			if (isVariable)
			{
				var formatString = this.IsGlobal
					? Config.VariableSynopsisGlobal
					: Config.VariableSynopsis;

				var itemName = this.IsGlobal
					? this.Name
					: this.FullName;

				return extended
					? string.Format(formatString, itemName, Config.MakeLink(this.TypeUrl, this.Type))
					: string.Format(formatString, itemName, this.Type);
			}

			return extended
				? string.Format(Config.PropertySynopsis, this.Parent.Name, this.Name, Config.MakeLink(this.TypeUrl, this.Type))
				: string.Format(Config.PropertySynopsis, this.Parent.Name, this.Name, this.Type);
		}
	}
}
